home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / amiga / fd2inlin.lha / fd2inline / RCS / fd2inline.c,v
Text File  |  1992-03-23  |  32KB  |  1,378 lines

  1. head     1.2;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    baron:1.2; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.2
  10. date     92.03.23.12.41.13;  author baron;  state Exp;
  11. branches ;
  12. next     1.1;
  13.  
  14. 1.1
  15. date     92.03.11.19.41.31;  author baron;  state Exp;
  16. branches ;
  17. next     ;
  18.  
  19.  
  20. desc
  21. @Parse an fd file and output inline definitions and the like.
  22. @
  23.  
  24.  
  25. 1.2
  26. log
  27. @First 0.9 distribution to Markus Wild only.
  28. @
  29. text
  30. @/*
  31.  *  fd2inline
  32.  *
  33.  * should be able to parse CBM fd files and generate vanilla inline calls
  34.  * for gcc. Works as a filter. This is a 0.9 evaluation version. Don't expect
  35.  * miracles (yet...).
  36.  *
  37.  * by Wolfgang Baron, all rights reserved.
  38.  *
  39.  */
  40.  
  41. /* $Id: fd2inline.c,v 1.2 92/03/23 12:38:05 baron Exp Locker: baron $ */
  42.  
  43. #include <stddef.h>
  44. #include <stdlib.h>
  45. #include <stdio.h>
  46. #include <string.h>
  47.  
  48. /*
  49.  * The program has a few sort of class definitions, which are the result of
  50.  * object oriented thinking, to be imlemented in plain C. I just haven't
  51.  * had the time to learn C++ or install the compiler. The design does however
  52.  * improve robustness, which allows the source to be used over and over again.
  53.  * if you use this code, please leave a little origin note.
  54.  *
  55.  */
  56.  
  57.  
  58.  
  59. const char *version_str= "$VER: fd2inline $Revision$ $Date$";
  60.  
  61. /*
  62.  * These are general definitions including types for defining registers etc.
  63.  */
  64.  
  65. #ifdef WDEBUG
  66. # define DBP(a) printf2 a
  67.  
  68. void printf2( const char *fmt, ... )
  69. {
  70.   vfprintf( stderr, fmt, (char *)(&fmt+1) );
  71. }
  72.  
  73. #else
  74. # define DBP(a)
  75. #endif
  76.  
  77.  
  78. #define REGS 16  /* d0=0,...,a7=15 */
  79.  
  80. typedef enum {
  81.   d0, d1, d2, d3, d4, d5, d6, d7, a0, a1, a2, a3, a4, a5, a6, a7, illegal
  82. } regs;
  83.  
  84. typedef unsigned char uchar, shortcard;
  85. typedef unsigned long ulong;
  86.  
  87. typedef enum { false, nodef, real_error } Error;
  88.  
  89.  
  90.  
  91. /*
  92.  * just some support functions, no checking
  93.  */
  94.  
  95. char *NewString( char **new, const char * old )
  96. {
  97.     const char *high;
  98.     ulong len;
  99.  
  100.   while ( *old && (' ' == *old || '\t' == *old) ) old++;
  101.   len= strlen( old );
  102.   for (high=old+len-1; high>=old && (' ' == *high || '\t' == *high); high-- );
  103.   high++;
  104.   len= high-old;
  105.   *new = (char *)malloc( 1+len );
  106.   if (*new) {
  107.     strncpy( *new, old, len );
  108.     (*new)[len]= '\0'; }
  109.   else {
  110.     fprintf( stderr, "no mem for string\n" ); }
  111.   return *new;
  112. }
  113.  
  114. void illparams( const char *funcname )
  115. {
  116.   fprintf( stderr, "%s: illegal Parameters\n", funcname );
  117. }
  118.  
  119.  
  120. const char * RegStr( regs reg )
  121. {
  122.     const char *myregs[]= {
  123.       "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  124.       "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "illegal" };
  125.  
  126.   if ( reg > illegal ) reg= illegal;
  127.   if ( reg < d0 )      reg= d0;
  128.   return myregs[reg];
  129. }
  130.  
  131.  
  132. /*
  133.  *    StrNRBrk
  134.  *
  135.  * searches string in from position at downwards, as long as in does not
  136.  * contain any character in not.
  137.  *
  138.  */
  139. const char * StrNRBrk( const char * in, const char *not, const char * at )
  140. {
  141.     const char *chcheck;
  142.     Error ready;
  143.  
  144.   chcheck = "";   /* if at<in, the result will be NULL */
  145.   for (ready=false; ready==false && at>=in; ) {
  146.     for (chcheck=not; *chcheck && *chcheck != *at; chcheck++);
  147.     if (*chcheck) ready= real_error;
  148.     else at--;
  149.   }
  150.   DBP(( "{%c}", *chcheck ));
  151.   return *chcheck ? at : NULL;
  152. }
  153.  
  154.  
  155.  
  156. /*
  157.  *    binSearch
  158.  *
  159.  * A binary search routine, wich operates on an array like you would use
  160.  * for qsort. The prototype does not contain the (*) bug...
  161.  *
  162.  * returns the address of the (a?) fitting object, or NULL;
  163.  *
  164.  * the binary intersection is (low+high)/2, so the highest value will never
  165.  * be reached, but the lowest value will. In the while condition, the diff
  166.  * has to be called last in case we got an empty array.
  167.  *
  168.  */
  169. void *binSearch ( void ** array, size_t elements, const void *lookfor,
  170.           int cmpfunc(const void **, const void **))
  171. {
  172.     size_t low, high, index;
  173.     int    diff;
  174.  
  175.   DBP(( "bs(%ld): ", (long)elements ));
  176.   diff= 1;    /* this needs to be so in case we got an empty array... */
  177.   low=0, high= elements;  /* our algorithm never reaches elements */
  178.   while( index= (high+low)/2,  /* somewhere inbetween */
  179.      high!=low && (diff= cmpfunc((const void **)array+index,&lookfor)) ) {
  180.     if (0<diff) {
  181.       high= index;  /* our value was too big, so grow downwards */
  182.       DBP(( "<" )); }
  183.     else {
  184.       low= index + 1;       /* the low value will be reached */
  185.       DBP(( ">" )); }
  186.     DBP(( "%ld ", (long)index ));
  187.   }
  188.   DBP(( "->%ld\n", diff ? -1L : (long)index ));
  189.   return diff ? NULL : array[index];  /* bingo */
  190. }
  191.  
  192.  
  193.  
  194.  
  195. /*
  196.  *    CLASS fdFile
  197.  *
  198.  * stores a file with a temporary buffer (static length, sorry), a line number,
  199.  * an offset (used for library offsets and an error field.
  200.  * When there's no error, line will contain line #lineno and offset will be
  201.  * the last offset set by the interpretation of the last line. If there's been
  202.  * no ##bias line, this field assumes a bias of 30, which is the standard bias.
  203.  * It is assumed offsets are always negative.
  204.  */
  205.  
  206. #define fF_BUFSIZE 1024
  207. #define fF_BUFFMT  "%1024[~▀]"
  208.  
  209.  
  210. /* all you need to know about an fdFile you parse */
  211. typedef struct {
  212.     FILE * file;        /* the file we're reading from  */
  213.     char   line[ fF_BUFSIZE ];    /* the current line        */
  214.     ulong  lineno;        /* current line number        */
  215.     long   offset;        /* current fd offset (-bias)    */
  216.     Error  error;        /* is everything o.k.        */
  217. } fdFile;
  218.  
  219.  
  220. fdFile       * fF_ctor(       const char *fname );
  221. void         fF_dtor(             fdFile *obj );
  222. void         fF_SetError(         fdFile *obj, Error error );
  223. void         fF_SetOffset(        fdFile *obj, long at );
  224. Error         fF_readln(           fdFile *obj );
  225. Error         fF_GetError(   const fdFile *obj );
  226. long         fF_GetOffset(  const fdFile *obj );
  227. char       * fF_FuncName(         fdFile *obj );       /* return name or null */
  228.  
  229.  
  230.  
  231.  
  232. fdFile * fF_ctor( const char *fname )
  233. {
  234.     fdFile * result;
  235.  
  236.   if (fname) {
  237.     result= (fdFile *) malloc( sizeof(fdFile) );
  238.     if (result) {
  239.       result->file= fopen( fname, "r" );
  240.       if (result->file) {
  241.     result->lineno= 0;
  242.     fF_SetOffset( result, -30);
  243.     fF_SetError( result, false );
  244.     result->line[0]= '\0';
  245.       }
  246.     } }
  247.   else {
  248.     result= NULL;
  249.     illparams( "fF_ctor" ); }
  250.   return result;
  251. }
  252.  
  253.  
  254.  
  255. void fF_dtor( fdFile *obj )
  256. {
  257.   fclose( obj->file );
  258.   free( obj );
  259. }
  260.  
  261.  
  262.  
  263. void fF_SetError( fdFile *obj, Error error )
  264. {
  265.   if (obj)
  266.     obj->error= error;
  267.   else
  268.     illparams( "fF_SetError" );
  269. }
  270.  
  271.  
  272.  
  273. void fF_SetOffset( fdFile *obj, long at )
  274. {
  275.   if (obj)
  276.     obj->offset= at;
  277.   else
  278.     illparams( "fFSetOffset" );
  279. }
  280.  
  281.  
  282.  
  283. Error fF_readln( fdFile *obj )
  284. {
  285.     char *low, *bpoint;
  286.     long glen, /* the length we read until now */
  287.     len;       /* the length of the last segment */
  288.  
  289.   if (obj) {
  290.     low= obj->line;
  291.     glen= 0;
  292.     do {
  293.       obj->lineno++;
  294.       if (!fgets( low, fF_BUFSIZE-1-glen, obj->file )) {
  295.     fF_SetError( obj, real_error );
  296.     obj->line[0]= '\0';
  297.     return real_error; }
  298.       if (low==strpbrk(low,"*#/")) {
  299.     DBP(( "in# %s\n", obj->line ));
  300.     return false; }
  301.       len= strlen( low );
  302.       bpoint= low+len-1;
  303.       if ('\n'==*bpoint) *bpoint='\0', bpoint--, len--;
  304.       if (';'==*bpoint || ')'==*bpoint ) {
  305.     DBP(( "\nin: %s\n", obj->line ));
  306.     return false; }
  307.       glen+= len;
  308.       low+= len;
  309.       if (glen >= fF_BUFSIZE-10) {      /* somewhat pessimistic ? */
  310.     fF_SetError(obj, real_error);
  311.     fprintf( stderr, "line %lu too long.\n", obj->lineno );
  312.     return real_error;
  313.       }
  314.       DBP(( "+" ));
  315.     } while (!0);
  316.   }
  317.   illparams( "fF_readln" );
  318.   return real_error;
  319. }
  320.  
  321.  
  322.  
  323. /*
  324.  *    fF_FuncName
  325.  *
  326.  * checks if it can find a function-name and return it's address, or NULL
  327.  * if the current line does not semm to contain one. The return value will
  328.  * be a pointer into a malloced buffer, thus the caller will have to free().
  329.  */
  330. char * fF_FuncName( fdFile *obj )
  331. {
  332.     const char *lower;
  333.     const char *upper;
  334.     char *buf;
  335.     long obraces;    /* count of open braces */
  336.     Error ready;    /* ready with searching */
  337.  
  338.   if (!obj || real_error==fF_GetError(obj)) {
  339.     illparams( "fF_FuncName" );
  340.     return NULL;
  341.   }
  342.   if (obj->line==strpbrk(obj->line, "#*/")) {
  343.     fF_SetError( obj, nodef );
  344.     return NULL;
  345.   }
  346.  
  347.   lower= NULL;
  348.   buf= NULL;
  349.   if (obj && false == fF_GetError(obj)) {
  350.     if ( upper=strrchr(obj->line, ')' )) {
  351.       DBP(( "end:%s:", upper ));
  352.       for(obraces= 1, ready= false; false== ready; upper=lower ) {
  353.     lower= StrNRBrk( obj->line, "()", --upper );
  354.     if (lower) {
  355.       switch (*lower) {
  356.         case ')': {
  357.           obraces++;
  358.           DBP(( " )%ld%s", obraces, lower ));
  359.           break; }
  360.         case '(': {
  361.           obraces--;
  362.           DBP(( " (%ld%s", obraces, lower ));
  363.           if (!obraces) ready= nodef;
  364.           break; }
  365.         default: {
  366.           fprintf( stderr, "faulty StrNRBrk\n" );
  367.         }
  368.       } }
  369.     else {
  370.       fprintf( stderr, "'(' or ')' expected in line %lu.\n", obj->lineno );
  371.       ready= real_error;
  372.     }
  373.       }
  374.       if (nodef==ready) {   /* we found the matching '(' */
  375.       long newlen;
  376.     upper--;
  377.     while (upper>=obj->line && (' ' == *upper || '\t' == *upper) ) upper--;
  378.     lower= StrNRBrk( obj->line, " \t*)", upper );
  379.     if (!lower) lower=obj->line;
  380.     else lower++;
  381.     newlen= upper-lower+2;
  382.     buf= malloc( newlen );
  383.     if (buf) {
  384.       strncpy( buf, lower, --newlen );
  385.       buf[newlen]= '\0';
  386.     }
  387.     else fprintf( stderr, "no mem for fF_FuncName" );
  388.       }
  389.     }
  390.   }
  391.   else illparams( "fF_FuncName" );
  392.   return buf;
  393. }
  394.  
  395.  
  396.  
  397. Error fF_GetError( const fdFile *obj )
  398. {
  399.   if (obj) return obj->error;
  400.   illparams( "fF_GetError" );
  401.   return real_error;
  402. }
  403.  
  404.  
  405.  
  406. long fF_GetOffset( const fdFile *obj )
  407. {
  408.   if (obj) return obj->offset;
  409.   illparams( "fF_GetOffset" );
  410.   return -1;
  411. }
  412.  
  413.  
  414.  
  415. /* ####################################################################### */
  416. /* ####################################################################### */
  417. /* ####################################################################### */
  418.  
  419. /*
  420.  *    CLASS fdDef
  421.  */
  422.  
  423.  
  424. typedef struct {
  425.   char * name;
  426.   char * type;
  427.   long     offset;
  428.   regs     reg[REGS];
  429.   char * param[REGS];
  430.   char * proto[REGS];
  431. } fdDef;
  432.  
  433. fdDef       * fD_ctor(      void );
  434. void         fD_dtor(            fdDef *obj );
  435. void         fD_NewName(         fdDef *obj, const char *newname );
  436. void         fD_NewParam(        fdDef *obj, shortcard at, const char * newstr );
  437. void         fD_NewProto(        fdDef *obj, shortcard at, const char * newstr );
  438. void         fD_NewReg(          fdDef *obj, shortcard at, regs reg );
  439. void         fD_NewType(         fdDef *obj, const char * newstr );
  440. void         fD_SetOffset(       fdDef *obj, long off );
  441. Error         fD_parsefd(         fdDef *obj, fdFile * infile );
  442. Error         fD_parsepr(         fdDef *obj, fdFile * infile );
  443. const char * fD_GetName(   const fdDef *obj );
  444. long         fD_GetOffset( const fdDef *obj );
  445. const char * fD_GetParam(  const fdDef *obj, shortcard at );
  446. regs         fD_GetReg(    const fdDef *obj, shortcard at );
  447. const char * fD_GetRegStr( const fdDef *obj, shortcard at );
  448. const char * fD_GetType(   const fdDef *obj );
  449. shortcard    fD_ParamNum(  const fdDef *obj );
  450. shortcard    fD_ProtoNum(  const fdDef *obj );
  451. shortcard    fD_RegNum(    const fdDef *obj );
  452. int         fD_cmpName(   const fdDef **big, const fdDef **small );
  453. void         fD_write(     const fdDef *obj );
  454.  
  455. char * fD_nostring = "";
  456.  
  457.  
  458.  
  459. fdDef * fD_ctor( void )
  460. {
  461.     fdDef * result;
  462.     regs    count;
  463.  
  464.   result= (fdDef *) malloc(sizeof(fdDef));
  465.   if (result) {
  466.     result->name= fD_nostring;
  467.     result->type= fD_nostring;
  468.     for ( count=d0; count<illegal; count++ ) {
  469.       result->reg[count]= illegal;
  470.       result->param[count]= fD_nostring;   /* if (!strlen) dont't free() */
  471.       result->proto[count]= fD_nostring;
  472.     } }
  473.   return result;
  474. }
  475.  
  476.  
  477.  
  478. /* free all resources and make the object as illegal as possible */
  479. void fD_dtor( fdDef * obj )
  480. {
  481.     regs count;
  482.  
  483.   if (obj) {
  484.     if (!obj->name) fprintf( stderr, "fD_dtor: null name" );
  485.     else if (obj->name != fD_nostring) free( obj->name );
  486.     if (!obj->type) fprintf( stderr, "fD_dtor: null type" );
  487.     else if (obj->type != fD_nostring) free( obj->type );
  488.     obj->name= obj->type= NULL;
  489.     for (count= d0; count<illegal; count++) {
  490.       obj->reg[count]= illegal;
  491.       if (!obj->param[count]) fprintf( stderr, "fD_dtor: null param" );
  492.       else if (obj->param[count] != fD_nostring) free(obj->param[count]);
  493.       if (!obj->proto[count]) fprintf( stderr, "fD_dtor: null proto" );
  494.       else if (obj->proto[count] != fD_nostring) free(obj->proto[count]);
  495.       obj->param[count]= obj->proto[count]= NULL; }
  496.     free(obj);
  497.   }
  498.   else fprintf( stderr, "dfDef_dtor(NULL)\n" );
  499. }
  500.  
  501.  
  502.  
  503. void fD_NewName( fdDef *obj, const char *newname )
  504. {
  505.   if (obj && newname) {
  506.     if (obj->name && fD_nostring != obj->name ) free( obj->name );
  507.     if (!NewString( &obj->name, newname )) obj->name= fD_nostring; }
  508.   else illparams( "fD_NewName" );
  509. }
  510.  
  511.  
  512.  
  513. void fD_NewParam( fdDef *obj, shortcard at, const char * newstr )
  514. {
  515.     char * pa;
  516.  
  517.   if (newstr && obj && at>=d0 && at<illegal) {
  518.     pa= obj->param[at];
  519.     if (pa && fD_nostring != pa) free( pa );
  520.     if (NewString( &pa, newstr)) {
  521.       obj->param[at]= pa; }
  522.     else {
  523.       obj->param[at]= fD_nostring;
  524.     } }
  525.   else illparams( "fD_NewParam" );
  526. }
  527.  
  528.  
  529.  
  530. void fD_NewProto( fdDef *obj, shortcard at, const char * newstr )
  531. {
  532.     char * pr;
  533.  
  534.   if (newstr && obj && at>=d0 && at<illegal) {
  535.     pr= obj->proto[at];
  536.     if (pr && fD_nostring != pr) free( pr );
  537.     if (NewString( &pr, newstr)) {
  538.       obj->proto[at]= pr; }
  539.     else {
  540.       obj->proto[at]= fD_nostring;
  541.     } }
  542.   else illparams( "fD_NewProto" );
  543. }
  544.  
  545.  
  546.  
  547. void fD_NewReg( fdDef *obj, shortcard at, regs reg )
  548. {
  549.   if (obj && at>=d0 && at<illegal && reg>=d0 && reg<=illegal) {
  550.     obj->reg[at] = reg; }
  551.   else illparams( "fD_NewReg" );
  552. }
  553.  
  554.  
  555.  
  556. void fD_NewType( fdDef *obj, const char *newtype )
  557. {
  558.   if (obj && newtype) {
  559.     if (obj->type && fD_nostring != obj->type ) free( obj->type );
  560.     if (!NewString( &obj->type, newtype )) obj->type= fD_nostring; }
  561.   else illparams( "fD_NewType" );
  562. }
  563.  
  564.  
  565.  
  566. void fD_SetOffset( fdDef *obj, long off )
  567. {
  568.   if (obj) {
  569.     obj->offset=off; }
  570.   else {
  571.     illparams( "fD_SetOffset" );
  572.   }
  573. }
  574.  
  575.  
  576.  
  577. /*    fD_parsefd
  578.  *
  579.  *  parse the current line. Needs to copy input, in order to insert \0's
  580.  *  RETURN
  581.  *    fF_GetError(infile):
  582.  *    false = read a definition.
  583.  *    nodef = not a definition on line (so try again)
  584.  *    error = real error
  585.  */
  586. Error fD_parsefd( fdDef * obj, fdFile * infile )
  587. {
  588.     enum  parse_info { name, params, regs, ready } parsing;
  589.     char  *buf, *bpoint, *bnext;
  590.     ulong index;
  591.  
  592.   if (obj && infile && (false == fF_GetError(infile))) {
  593.     parsing= name;
  594.     if (!NewString( &buf, infile->line )) {
  595.       fprintf( stderr, "no mem for line %lu\n", infile->lineno );
  596.       fF_SetError( infile, real_error );
  597.     }
  598.     bpoint= buf;  /* so -Wall keeps quiet */
  599.     /* printf("copied %lu: %s", infile->lineno, buf ); */
  600.  
  601.     /* try to parse the line until there's an error or we are done */
  602.     while (ready != parsing && false == fF_GetError(infile)) {
  603.       switch (parsing) {
  604.     case name: {
  605.  
  606.       switch (buf[0]) {
  607.         case '#': {
  608.           if (!strncmp("##bias", buf, 6)) {
  609.         if (1!=sscanf( buf+6, "%ld", &infile->offset )) {
  610.           fprintf( stderr, "illegal ##bias in line %lu: %s\n",
  611.                infile->lineno, infile->line );
  612.           fF_SetError( infile, real_error );
  613.           break; } /* avoid nodef */
  614.         else {
  615.           if (fF_GetOffset(infile) > 0)
  616.             fF_SetOffset(infile, -fF_GetOffset(infile));
  617.           /* printf("set offset to %ld\n", fFGetOffset(infile); */
  618.         }
  619.           } }                /* drop through for error */
  620.         case '*': {                     /* comment */
  621.           fF_SetError( infile, nodef ); /* try again somewhere else */
  622.           break; }
  623.         default: {      /* assume a regular line here */
  624.           parsing= name;
  625.           /* switch (parsing) */
  626.           for (index=0; buf[index] && buf[index]!='('; index++ );
  627.           if (!buf[index]) {  /* oops, no fd ? */
  628.         fprintf( stderr, "not an fd, line %lu: %s\n",
  629.              infile->lineno, buf /* infile->line */ );
  630.         fF_SetError(infile, nodef); } /* maybe next time */
  631.           else {
  632.         buf[index]=0;
  633.         fD_NewName( obj, buf );
  634.         fD_SetOffset( obj, fF_GetOffset(infile) );
  635.         bpoint= buf+index+1;
  636.         parsing= params;      /* continue the loop */
  637.           }
  638.         } }
  639.       break; }
  640.     case params: {
  641.         char *bptmp;    /* needed for fD_NewParam */
  642.       /* look for parameters now */
  643.       for ( bnext= bpoint
  644.           ; *bnext && *bnext!=',' && *bnext!=')'
  645.           ; bnext++ );
  646.       if (*bnext) {
  647.         bptmp=bpoint;
  648.         if (')'==*bnext) {
  649.           if ('('!=bnext[1]) {
  650.         fprintf( stderr, "registers expected in line %lu: %s\n",
  651.              infile->lineno, infile->line );
  652.         fF_SetError(infile, nodef); }
  653.           else {
  654.         parsing= regs;
  655.         bpoint= bnext+2;
  656.           }
  657.         }
  658.         else bpoint= bnext+1;
  659.         /* terminate string and advance to next item */
  660.         *bnext= '\0';
  661.         fD_NewParam( obj, fD_ParamNum(obj), bptmp );
  662.       }
  663.       else {
  664.         fF_SetError(infile, nodef);
  665.         fprintf( stderr, "param expected in line %lu: %s\n",
  666.              infile->lineno, infile->line );
  667.       }
  668.       break; } /* switch parsing */
  669.     case regs: {
  670.       /* look for parameters now */
  671.       for ( bnext= bpoint
  672.           ; *bnext && *bnext!='/' && *bnext!=',' && *bnext!=')'
  673.           ; bnext++ );
  674.       if (*bnext) {
  675.         if (')'==*bnext) {    /* wow, we've finished */
  676.           fF_SetOffset( infile, fF_GetOffset(infile)-6 );
  677.           parsing= ready;
  678.         }
  679.         *bnext= '\0';
  680.         if (   ('d'==bpoint[0] || 'a'==bpoint[0])
  681.         && '0'<=bpoint[1] && '8'>=bpoint[1] && bnext == bpoint+2)
  682.           fD_NewReg( obj, fD_RegNum(obj),
  683.              bpoint[1]-'0'+(bpoint[0]=='a'?8:0) );
  684.         else if (bnext!=bpoint) { /* it is when our function is void */
  685.           fprintf( stderr, "illegal register %s in line %ld\n",
  686.                bpoint, infile->lineno );
  687.           fF_SetError(infile, nodef); }
  688.         bpoint= bnext+1;
  689.       }
  690.       else {
  691.         fF_SetError(infile, nodef);
  692.         fprintf( stderr, "reg expected in line %lu\n", infile->lineno );
  693.       }
  694.       break; }  /* switch parsing */
  695.     case ready: {
  696.       fprintf( stderr, "internal error, use another compiler.\n" );
  697.       break;
  698.     }
  699.       } }
  700.     free( buf );
  701.     return fF_GetError(infile); }
  702.   else {
  703.     illparams( "fD_parsefd" );
  704.     return real_error;
  705.   }
  706. }
  707.  
  708.  
  709.  
  710. Error fD_parsepr( fdDef *obj, fdFile * infile )
  711. {
  712.     char *buf;        /* a copy of infile->line              */
  713.     char *bpoint,   /* cursor in buf                  */
  714.      *bnext,    /* looking for the end              */
  715.      *lowarg;   /* beginning of this argument          */
  716.     long obraces;   /* count of open braces              */
  717.     regs count,     /* count parameter number              */
  718.      args;        /* the number of arguments for this function  */
  719.  
  720.   if (!(obj && infile && false==fF_GetError(infile))) {
  721.     illparams( "fD_parsepr" );
  722.     fF_SetError( infile, real_error );
  723.     return real_error;
  724.   }
  725.  
  726.   if (!NewString( &buf, infile->line )) {
  727.     fprintf( stderr, "no mem for fD_parsepr\n" );
  728.     fF_SetError( infile, real_error );
  729.     return real_error;
  730.   }
  731.  
  732.   fF_SetError( infile, false );
  733.   if (bpoint= strstr( buf, fD_GetName(obj) ) ) {
  734.     while (--bpoint>=buf && (' '== *bpoint || '\t'== *bpoint)) bpoint--;
  735.     *++bpoint= '\0';
  736.     fD_NewType( obj, buf );
  737.     while(bpoint && '('!=*bpoint++);        /* one beyond '(' */
  738.     lowarg= bpoint;
  739.     obraces= 0;
  740.     for (count=0, args=fD_RegNum(obj); count<args; bpoint= bnext+1 ) {
  741.       while(*bpoint && ' '==*bpoint) bpoint++; /* ignore spaces */
  742.       bnext= strpbrk( bpoint, "()," );
  743.       if (bnext) {
  744.     switch (*bnext) {
  745.       case '(': {
  746.         obraces++;
  747.         DBP(( "< (%ld%s >", obraces, bnext ));
  748.         break; }
  749.       case ')': {
  750.         if (obraces) {
  751.           DBP(( "< )%ld%s >", obraces, bnext ));
  752.           obraces--; }
  753.         else {
  754.           *bnext= '\0';
  755.           DBP(( "< )0> [LAST PROTO=%s]", lowarg ));
  756.           fD_NewProto( obj, count, lowarg );
  757.           lowarg= bnext+1;
  758.           if (count!=args-1) {
  759.         /*
  760.         fprintf( stderr, "%s needs %u arguments and got %u.\n",
  761.              fD_GetName(obj), args, count+1 );
  762.         */
  763.         fF_SetError( infile, nodef ); }
  764.           count++; }
  765.         break; }
  766.       case ',': {
  767.         if (!obraces) {
  768.           *bnext= '\0';
  769.           DBP(( " [PROTO=%s] ", lowarg ));
  770.           fD_NewProto( obj, count, lowarg );
  771.           lowarg= bnext+1;
  772.           count++; }
  773.         break; }
  774.       default: {
  775.         fprintf( stderr, "faulty strpbrk in line %lu.\n", infile->lineno );
  776.       }
  777.     } }
  778.       else {
  779.     /*
  780.     fprintf( stderr, "faulty argument %u in line %lu.\n",
  781.          count+1, infile->lineno );
  782.     */
  783.     count=args; /* this will effectively quit the for loop */
  784.     fF_SetError( infile, nodef );
  785.       }
  786.     }
  787.     if (fD_ProtoNum(obj) != fD_RegNum(obj)) {
  788.       fF_SetError( infile, nodef );
  789.     }
  790.   }
  791.   else {
  792.     fprintf( stderr, "fD_parsepr was fooled in line %lu\n", infile->lineno );
  793.     fprintf( stderr, "function , definition %s.\n",
  794.          /* fD_GetName(obj),*/ infile->line );
  795.     fF_SetError( infile, nodef );
  796.   }
  797.  
  798.   free( buf );
  799.   return fF_GetError(infile);
  800. }
  801.  
  802.  
  803.  
  804. const char * fD_GetName( const fdDef *obj )
  805. {
  806.   if (obj && obj->name) {
  807.     return obj->name; }
  808.   else {
  809.     illparams( "fD_GetName" );
  810.     return fD_nostring;
  811.   }
  812. }
  813.  
  814.  
  815.  
  816. long fD_GetOffset( const fdDef *obj )
  817. {
  818.   if (obj) {
  819.     return obj->offset; }
  820.   else {
  821.     illparams( "fD_GetOffset" );
  822.     return 0;
  823.   }
  824. }
  825.  
  826.  
  827.  
  828. const char * fD_GetProto( const fdDef *obj, shortcard at )
  829. {
  830.   if (obj && at>=d0 && at<illegal && obj->proto[at]) {
  831.     return obj->proto[at]; }
  832.   else {
  833.     illparams( "fD_GetProto" );
  834.     return fD_nostring;
  835.   }
  836. }
  837.  
  838.  
  839.  
  840. const char * fD_GetParam( const fdDef *obj, shortcard at )
  841. {
  842.   if (obj && at>=d0 && at<illegal && obj->param[at]) {
  843.     return obj->param[at]; }
  844.   else {
  845.     illparams( "fD_GetParam" );
  846.     return fD_nostring;
  847.   }
  848. }
  849.  
  850.  
  851.  
  852. regs fD_GetReg( const fdDef *obj, shortcard at )
  853. {
  854.   if (obj && at>=d0 && at<illegal) {
  855.     return obj->reg[at]; }
  856.   else {
  857.     illparams( "fD_GetReg" );
  858.     return illegal;
  859.   }
  860. }
  861.  
  862.  
  863.  
  864. const char *fD_GetRegStr( const fdDef *obj, shortcard at )
  865. {
  866.   if (obj && at>=d0 && at<illegal) {
  867.     return RegStr( obj->reg[at] ); }
  868.   else {
  869.     illparams( "fD_GetReg" );
  870.     return RegStr( illegal );
  871.   }
  872. }
  873.  
  874.  
  875.  
  876. const char * fD_GetType( const fdDef *obj )
  877. {
  878.   if (obj && obj->type) {
  879.     return obj->type; }
  880.   else {
  881.     illparams( "fD_GetType" );
  882.     return fD_nostring;
  883.   }
  884. }
  885.  
  886.  
  887.  
  888. /* get first free param or illegal */
  889. shortcard fD_ParamNum( const fdDef *obj )
  890. {
  891.     shortcard count;
  892.  
  893.   if (obj) {
  894.     for ( count= d0; count<illegal && fD_nostring!=obj->param[count]; count++ );
  895.     return count; }
  896.   else {
  897.     illparams( "fD_ParamNum" );
  898.     return illegal;
  899.   }
  900. }
  901.  
  902.  
  903.  
  904. shortcard fD_ProtoNum( const fdDef *obj )
  905. {
  906.     shortcard count;
  907.  
  908.   if (obj) {
  909.     for ( count= d0; count<illegal && fD_nostring!=obj->proto[count]; count++ );
  910.     return count; }
  911.   else {
  912.     illparams( "fD_ProtoNum" );
  913.     return illegal;
  914.   }
  915. }
  916.  
  917.  
  918.  
  919. /* get first free *reg or illegal */
  920. shortcard fD_RegNum( const fdDef *obj )
  921. {
  922.     shortcard count;
  923.  
  924.   if (obj) {
  925.     for ( count= d0; count<illegal && illegal!=obj->reg[count]; count++ );
  926.     return count; }
  927.   else {
  928.     illparams( "fD_RegNum" );
  929.     return illegal;
  930.   }
  931. }
  932.  
  933.  
  934.  
  935. int fD_cmpName( const fdDef **big, const fdDef **small )  /* for qsort */
  936. {
  937.     int res;
  938.   res = strcmp( fD_GetName( *big ), fD_GetName( *small ) );
  939.   return res;
  940. }
  941.  
  942.  
  943. void fD_write( const fdDef * obj )
  944. {
  945.     shortcard count, numregs;
  946.     const char *chtmp;
  947.  
  948.   DBP(("func %s\n", fD_GetName(obj) ));
  949.   numregs= fD_RegNum(obj);
  950.   if (fD_nostring == fD_GetType(obj)) {
  951.     fprintf( stderr, "%s has no prototype.\n", fD_GetName(obj) );
  952.     return; }
  953.   if (fD_ProtoNum(obj) != numregs) {
  954.     fprintf( stderr, "%s gets %ld fd args and %ld proto%s.\n",
  955.          fD_GetName(obj), numregs, fD_ProtoNum(obj),
  956.          fD_ProtoNum(obj) != 1 ? "s" : "" );
  957.     return;
  958.   }
  959.  
  960.   printf( "__inline static void %s( BASE_PAR_DECL", fD_GetName(obj) );
  961.   if (0<numregs) {
  962.     for( count=d0; count<numregs-1; count++) {
  963.       printf( " %s ", fD_GetProto(obj,count) );
  964.       printf( " %s,", fD_GetParam(obj,count) ); }
  965.     printf( " %s ", fD_GetProto(obj,count) );
  966.     printf( " %s", fD_GetParam(obj,count) ); }
  967.   else
  968.     putchar( '0' );
  969.   puts( " )\n{\n\tBASE_EXT_DECL\n\tregister res __asm(\"d0\");" );
  970.   puts( "\tregister void *a6 __asm(\"a6\");" );
  971.   for( count=d0; count<numregs; count++) {
  972.     chtmp= fD_GetRegStr(obj,count);
  973.     printf( "\tregister %s %s __asm(\"%s\");\n",
  974.         fD_GetProto(obj,count), chtmp, chtmp ); }
  975.   puts( "" );
  976.   puts( "\ta6 = BASE_NAME;" );
  977.   for( count=d0; count<numregs; count++)
  978.     printf( "\t%s = %s;\n", fD_GetRegStr(obj,count), fD_GetParam(obj,count) );
  979.   puts( "\t__asm volatile (\"" );
  980.   printf( "\tjsr a6@@(-0x%lx)\"\n", -fD_GetOffset(obj) );
  981.   puts( "\t: \"=r\" (res)" );
  982.   printf( "\t: \"r\" (a6)" );
  983.   for( count=d0; count<numregs; count++)
  984.     printf( " \"r\" (%s)", fD_GetRegStr(obj,count) );
  985.   printf( "\n\t: \"d0\", \"d1\", \"a0\", \"a1\"" );
  986.   for( count=d0; count<numregs; count++) {
  987.     switch (fD_GetReg(obj,count)) {
  988.       case d0:
  989.       case d1:
  990.       case a0:
  991.       case a1: break;
  992.       default: {
  993.     printf( ", \"%s\"", fD_GetRegStr(obj,count) );
  994.     break;
  995.       }
  996.     } }
  997.   printf( " );\n\treturn res;\n}\n" );
  998. }
  999.  
  1000.  
  1001.  
  1002.  
  1003.  
  1004. #define FDS 1000
  1005.  
  1006. void main ( int argc, char **argv )
  1007. {
  1008.     fdDef **mydef;
  1009.     fdDef *tmpdef= NULL,   /* a dummy to contain the name to look for */
  1010.       *founddef;       /* the fdDef for which we found a prototype */
  1011.     fdFile *myfile;
  1012.     char *tmpstr;
  1013.     long count, fds;
  1014.     Error lerror = false;
  1015.  
  1016.   if (3!=argc) {
  1017.     fprintf( stderr, "usage: %s fdfilename protofilename\n", argv[0] );
  1018.     exit(20);
  1019.   }
  1020.  
  1021.   mydef= malloc( FDS*sizeof(fdDef *) );
  1022.   if (mydef) {
  1023.     for( count=0; count<FDS; count++) mydef[count]= NULL;
  1024.     myfile= fF_ctor( argv[1] );
  1025.     if (myfile) {
  1026.       lerror= false;
  1027.       for (count= 0; count<FDS && false==lerror; count++ ) {
  1028.     mydef[count]= fD_ctor();
  1029.     do {
  1030.       if (false==(lerror=fF_readln(myfile))) {
  1031.         fF_SetError(myfile, false);
  1032.         lerror=fD_parsefd(mydef[count], myfile);
  1033.       }
  1034.     } while (nodef==lerror);
  1035.       }
  1036.       if (count<FDS) {
  1037.     count--;
  1038.     fD_dtor( mydef[count] );
  1039.     mydef[count]= NULL;
  1040.       }
  1041.       fds= count;
  1042.       /* the gnu stdlib.h seems to have a bug for qsort: int (*)(etc.) */
  1043.       qsort( mydef, count, sizeof(fdDef *), (void *)fD_cmpName );
  1044.       fF_dtor( myfile );
  1045.       myfile= fF_ctor( argv[2] );
  1046.       if (myfile) {
  1047.     if (!tmpdef) tmpdef= fD_ctor();
  1048.     for (lerror= false; false==lerror; ) {
  1049.       do {
  1050.         if (false==(lerror=fF_readln(myfile))) {
  1051.           fF_SetError( myfile, false );   /* continue even on errors */
  1052.           tmpstr= fF_FuncName( myfile );
  1053.           if (tmpstr) {
  1054.         fD_NewName( tmpdef, tmpstr );
  1055.         founddef= binSearch( (void **)mydef, fds, tmpdef, (void *)fD_cmpName );
  1056.         if (founddef) {
  1057.           DBP(("found (%s).\n", fD_GetName( founddef ) ));
  1058.           fF_SetError(myfile, false);
  1059.           lerror= fD_parsepr(founddef, myfile);
  1060.         }
  1061.         else fprintf( stderr, "did not find <%s> in line %lu.\n",
  1062.                   tmpstr, myfile->lineno );
  1063.         free( tmpstr );
  1064.           }
  1065.           else lerror= nodef;
  1066.         }
  1067.       } while (nodef==lerror);
  1068.     }
  1069.     fD_dtor(tmpdef);
  1070.     tmpdef= NULL;
  1071.       }
  1072.     }
  1073.     else fprintf( stderr, "Couldn't open file.\n" );
  1074.     for (count=0; count<FDS && mydef[count]; count++) {
  1075.       /* printf("outputting %ld...\n", count ); */
  1076.       fD_write( mydef[count] );
  1077.       fD_dtor( mydef[count] );
  1078.       mydef[count]= NULL; }
  1079.     fF_dtor( myfile );
  1080.     myfile= NULL;
  1081.     switch (lerror) {
  1082.       case false:      exit(0);
  1083.       case nodef:      exit(20);
  1084.       case real_error: exit(20);
  1085.       default:           exit(30);
  1086.     } }
  1087.   else {
  1088.     fprintf( stderr, "No mem for FDs\n" );
  1089.     exit(20);
  1090.   }
  1091. }
  1092.  
  1093.  
  1094. @
  1095.  
  1096.  
  1097. 1.1
  1098. log
  1099. @Initial revision
  1100. @
  1101. text
  1102. @d5 2
  1103. a6 1
  1104.  * for gcc. Works as a filter.
  1105. d12 1
  1106. a12 1
  1107. /* $Id$ */
  1108. d29 3
  1109. d36 13
  1110. d68 9
  1111. a76 1
  1112.   *new = (char *)malloc( 1+strlen(old) );
  1113. d78 2
  1114. a79 1
  1115.     strcpy( *new, old ); }
  1116. d91 74
  1117. d192 7
  1118. a198 4
  1119. void         fF_dtor(       fdFile *obj );
  1120. void         fF_SetOffset(  fdFile *obj, long at );
  1121. void         fF_SetError(   fdFile *obj, Error error );
  1122. Error         fF_readln(     fdFile *obj );
  1123. d213 1
  1124. a213 1
  1125.     result->offset= -30;
  1126. d234 1
  1127. a234 1
  1128. void fF_SetOffset( fdFile *obj, long at )
  1129. d237 1
  1130. a237 1
  1131.     obj->offset= at;
  1132. d239 1
  1133. a239 1
  1134.     illparams( "fFSetOffset" );
  1135. d244 1
  1136. a244 1
  1137. void fF_SetError( fdFile *obj, Error error )
  1138. d247 1
  1139. a247 1
  1140.     obj->error= error;
  1141. d249 1
  1142. a249 1
  1143.     illparams( "fFSetError" );
  1144. d256 3
  1145. d261 27
  1146. a287 6
  1147.     obj->lineno++;
  1148.     if (!fgets( obj->line, fF_BUFSIZE-1, obj->file )) {
  1149.       fF_SetError( obj, real_error);
  1150.       obj->line[0]=0;
  1151.       return real_error; }
  1152.     return false; }
  1153. d294 91
  1154. d386 3
  1155. d397 1
  1156. d401 1
  1157. d405 20
  1158. a424 13
  1159. void         fD_dtor(      fdDef *obj );
  1160. void         fD_NewName(   fdDef *obj, const char *newname );
  1161. void         fD_SetOffset( fdDef *obj, long off );
  1162. void         fD_NewParam(  fdDef *obj, shortcard at, const char * newstr );
  1163. void         fD_NewReg(    fdDef *obj, shortcard at, regs reg );
  1164. const char * fD_GetName(   fdDef *obj );
  1165. long         fD_GetOffset( fdDef *obj );
  1166. const char * fD_GetParam(  fdDef *obj, shortcard at );
  1167. regs         fD_GetReg(    fdDef *obj, shortcard at );
  1168. Error         fD_sparse(    fdDef *obj, fdFile * infile );
  1169. void         fD_write(     fdDef *obj );
  1170. shortcard    fD_ParamNum(  fdDef *obj );
  1171. shortcard    fD_RegNum(    fdDef *obj );
  1172. d437 2
  1173. a438 1
  1174.     result->name=0;
  1175. d442 1
  1176. d449 1
  1177. d455 5
  1178. d462 7
  1179. a468 2
  1180.       if (obj->param[count] != fD_nostring) free(obj->param[count]);
  1181.     } }
  1182. d477 1
  1183. a483 11
  1184. void fD_SetOffset( fdDef *obj, long off )
  1185. {
  1186.   if (obj) {
  1187.     obj->offset=off; }
  1188.   else {
  1189.     illparams( "fD_SetOffset" );
  1190.   }
  1191. }
  1192.  
  1193.  
  1194.  
  1195. a486 1
  1196.     size_t len;
  1197. d501 1
  1198. a501 1
  1199. void fD_NewReg( fdDef *obj, shortcard at, regs reg )
  1200. d503 1
  1201. a503 4
  1202.   if (obj && at>=d0 && at<illegal && reg>=d0 && reg<=illegal) {
  1203.     obj->reg[at] = reg; }
  1204.   else illparams( "fD_NewReg" );
  1205. }
  1206. d505 9
  1207. a513 10
  1208.  
  1209.  
  1210. long fD_GetOffset( fdDef *obj )
  1211. {
  1212.   if (obj) {
  1213.     return obj->offset; }
  1214.   else {
  1215.     illparams( "fD_GetOffset" );
  1216.     return 0;
  1217.   }
  1218. d518 1
  1219. a518 1
  1220. const char * fD_GetName( fdDef *obj )
  1221. d520 3
  1222. a522 15
  1223.   if (obj && obj->name) {
  1224.     return obj->name; }
  1225.   else {
  1226.     illparams( "fD_GetParam" );
  1227.     return fD_nostring;
  1228.   }
  1229. }
  1230.  
  1231.  
  1232.  
  1233. const char * fD_GetParam( fdDef *obj, shortcard at )
  1234. {
  1235.   if (obj && at>=d0 && at<illegal && obj->param[at]) {
  1236.     return obj->param[at]; }
  1237.   else illparams( "fD_GetParam" );
  1238. d527 1
  1239. a527 1
  1240. regs fD_GetReg( fdDef *obj, shortcard at )
  1241. d529 4
  1242. a532 3
  1243.   if (obj && at>=d0 && at<illegal) {
  1244.     return obj->reg[at]; }
  1245.   else illparams( "fD_GetReg" );
  1246. d537 1
  1247. a537 2
  1248. /* get first free ->param or illegal */
  1249. shortcard fD_ParamNum( fdDef *obj )
  1250. a538 2
  1251.     shortcard count;
  1252.  
  1253. d540 1
  1254. a540 2
  1255.     for ( count= d0; count<illegal && fD_nostring!=obj->param[count]; count++ );
  1256.     return count; }
  1257. d542 1
  1258. a542 18
  1259.     illparams( "fD_ParamNum" );
  1260.     return illegal;
  1261.   }
  1262. }
  1263.  
  1264.  
  1265.  
  1266. /* get first free ->reg or illegal */
  1267. shortcard fD_RegNum( fdDef *obj )
  1268. {
  1269.     shortcard count;
  1270.  
  1271.   if (obj) {
  1272.     for ( count= d0; count<illegal && illegal!=obj->reg[count]; count++ );
  1273.     return count; }
  1274.   else {
  1275.     illparams( "fD_RegNum" );
  1276.     return illegal;
  1277. d548 1
  1278. a548 1
  1279. /*    fD_sparse
  1280. d552 1
  1281. a552 1
  1282.  *    fdFile->error:
  1283. d557 1
  1284. a557 1
  1285. Error fD_sparse( fdDef * obj, fdFile * infile )
  1286. a558 1
  1287.     regs  count;
  1288. d561 1
  1289. a561 1
  1290.     ulong index, tmpindex;
  1291. d563 1
  1292. a563 1
  1293.   if (obj && infile && (false == infile->error)) {
  1294. d567 1
  1295. a567 1
  1296.       infile->error= real_error;
  1297. d569 1
  1298. d573 1
  1299. a573 1
  1300.     while (ready != parsing && false == infile->error) {
  1301. d583 1
  1302. a583 1
  1303.           infile->error= real_error;
  1304. d586 3
  1305. a588 2
  1306.           if (infile->offset > 0) infile->offset= -infile->offset;
  1307.           /* printf("set offset to %ld\n", infile->offset ); */
  1308. d590 3
  1309. a592 3
  1310.           } }              /* drop through for error */
  1311.         case '*': {               /* comment */
  1312.           infile->error = nodef;  /* try again somewhere else */
  1313. d600 2
  1314. a601 2
  1315.              infile->lineno, infile->line );
  1316.         infile->error= nodef; } /* maybe next time */
  1317. d605 1
  1318. a605 1
  1319.         fD_SetOffset( obj, infile->offset );
  1320. d623 1
  1321. a623 1
  1322.         infile->error= nodef; }
  1323. d635 1
  1324. a635 1
  1325.         infile->error= nodef;
  1326. d647 1
  1327. a647 1
  1328.           infile->offset -= 6;
  1329. d658 1
  1330. a658 1
  1331.           infile->error= nodef; }
  1332. d662 1
  1333. a662 1
  1334.         infile->error= nodef;
  1335. d665 4
  1336. a668 2
  1337.       break;  /* switch parsing */
  1338.  
  1339. d672 1
  1340. a672 1
  1341.     return infile->error; }
  1342. d674 26
  1343. a699 1
  1344.     illparams( "fD_sparse" );
  1345. d702 169
  1346. d875 14
  1347. d890 2
  1348. a891 1
  1349. void fD_write( fdDef * obj )
  1350. d894 7
  1351. a900 3
  1352.   printf("%ld %s ( ", fD_GetOffset(obj), fD_GetName(obj)  );
  1353.   for( count=d0; count<illegal && illegal!=fD_GetReg(obj,count); count++) {
  1354.     printf( "%s in %d, ", fD_GetParam(obj,count), (int)fD_GetReg(obj,count) );
  1355. d902 67
  1356. a968 1
  1357.   printf( ")\n" );
  1358. d980 2
  1359. d983 1
  1360. d985 1
  1361. a985 1
  1362.     Error lerror;
  1363. d987 2
  1364. a988 2
  1365.   if (2!=argc) {
  1366.     fprintf( stderr, "usage: %s fdfilename\n", argv[0] );
  1367. d1002 2
  1368. a1003 2
  1369.         myfile->error= false;
  1370.         lerror=fD_sparse(mydef[count], myfile);
  1371. d1012 31
  1372. d1044 1
  1373. d1048 2
  1374. a1049 1
  1375.       fD_dtor( mydef[count] ); }
  1376. d1051 1
  1377. @
  1378.